<template>
  <el-dialog
    v-model="dialogVisible"
    :title="`分配菜单 - ${roleData?.name || ''}`"
    width="600px"
    @close="handleClose"
  >
    <div class="menu-container">
      <el-tree
        ref="treeRef"
        :data="menuTree"
        :props="treeProps"
        show-checkbox
        node-key="id"
        :default-checked-keys="selectedMenus"
        :check-strictly="false"
        :expand-on-click-node="false"
        default-expand-all
      >
        <template #default="{ node, data }">
          <div class="menu-node">
            <div class="menu-info">
              <span class="menu-name">{{ data.name }}</span>
              <span class="menu-path" v-if="data.path">{{ data.path }}</span>
            </div>
            <div class="menu-meta" v-if="data.meta">
              <el-tag size="small" v-if="data.meta.title">{{ data.meta.title }}</el-tag>
              <el-tag size="small" type="info" v-if="data.meta.icon">
                <el-icon><component :is="data.meta.icon" /></el-icon>
              </el-tag>
              <el-tag size="small" type="warning" v-if="data.hidden">隐藏</el-tag>
            </div>
          </div>
        </template>
      </el-tree>
    </div>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleExpandAll">展开全部</el-button>
        <el-button @click="handleCollapseAll">收起全部</el-button>
        <el-button @click="handleClose">取消</el-button>
        <el-button type="primary" @click="handleSubmit" :loading="loading">
          确定
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import type { ElTree } from 'element-plus'
import { getAllMenuTree } from '@/api/menu'
import { getRoleMenus, updateRoleMenus, type Role } from '@/api/role'

interface Props {
  visible: boolean
  roleData?: Role | null
}

interface Emits {
  (e: 'update:visible', value: boolean): void
  (e: 'success'): void
}

interface MenuTreeNode {
  id: number
  parent_id?: number
  name: string
  path: string
  component: string
  redirect?: string
  meta?: {
    title?: string
    icon?: string
    affix?: boolean
    hidden?: boolean
    [key: string]: any
  }
  sort: number
  hidden: boolean
  children?: MenuTreeNode[]
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const treeRef = ref<InstanceType<typeof ElTree>>()
const loading = ref(false)
const menuTree = ref<MenuTreeNode[]>([])
const selectedMenus = ref<number[]>([])

// 对话框显示状态
const dialogVisible = computed({
  get: () => props.visible,
  set: (value) => emit('update:visible', value)
})

// 树形组件属性
const treeProps = {
  children: 'children',
  label: 'name'
}

// 监听对话框显示状态
watch(dialogVisible, (visible) => {
  if (visible && props.roleData) {
    loadAllMenus()
    loadRoleMenus()
  }
})

// 加载所有菜单树
async function loadAllMenus() {
  try {
    const menus = await getAllMenuTree()
    menuTree.value = menus
  } catch (error) {
    console.error('Failed to load menus:', error)
    ElMessage.error('加载菜单列表失败')
  }
}

// 加载角色菜单
async function loadRoleMenus() {
  if (!props.roleData) return

  try {
    const menus = await getRoleMenus(props.roleData.id)
    selectedMenus.value = menus.map(m => m.id)

    // 设置树形组件的选中状态
    if (treeRef.value) {
      treeRef.value.setCheckedKeys(selectedMenus.value)
    }
  } catch (error) {
    console.error('Failed to load role menus:', error)
    ElMessage.error('加载角色菜单失败')
  }
}

// 展开全部
function handleExpandAll() {
  if (treeRef.value) {
    // 获取所有节点的key
    const allKeys = getAllNodeKeys(menuTree.value)
    allKeys.forEach(key => {
      treeRef.value!.store.nodesMap[key].expanded = true
    })
  }
}

// 收起全部
function handleCollapseAll() {
  if (treeRef.value) {
    // 获取所有节点的key
    const allKeys = getAllNodeKeys(menuTree.value)
    allKeys.forEach(key => {
      treeRef.value!.store.nodesMap[key].expanded = false
    })
  }
}

// 获取所有节点的key
function getAllNodeKeys(nodes: MenuTreeNode[]): number[] {
  const keys: number[] = []

  function traverse(nodeList: MenuTreeNode[]) {
    nodeList.forEach(node => {
      keys.push(node.id)
      if (node.children && node.children.length > 0) {
        traverse(node.children)
      }
    })
  }

  traverse(nodes)
  return keys
}

// 提交菜单分配
async function handleSubmit() {
  if (!props.roleData || !treeRef.value) return

  // 获取选中的节点（包括半选中的父节点）
  const checkedKeys = treeRef.value.getCheckedKeys() as number[]
  const halfCheckedKeys = treeRef.value.getHalfCheckedKeys() as number[]
  const allSelectedKeys = [...checkedKeys, ...halfCheckedKeys]

  loading.value = true
  try {
    await updateRoleMenus(props.roleData.id, {
      menu_ids: allSelectedKeys
    })
    ElMessage.success('菜单分配成功')
    emit('success')
    handleClose()
  } catch (error) {
    console.error('Failed to update role menus:', error)
  } finally {
    loading.value = false
  }
}

// 关闭对话框
function handleClose() {
  dialogVisible.value = false
  selectedMenus.value = []
}

// 初始化
onMounted(() => {
  loadAllMenus()
})
</script>

<style scoped>
.menu-container {
  padding: 20px 0;
  max-height: 400px;
  overflow-y: auto;
}

.menu-node {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 4px 0;
}

.menu-info {
  display: flex;
  align-items: center;
  gap: 8px;
}

.menu-name {
  font-weight: 500;
  color: #333;
}

.menu-path {
  font-size: 12px;
  color: #666;
  background: #f5f5f5;
  padding: 2px 6px;
  border-radius: 3px;
  font-family: 'Courier New', monospace;
}

.menu-meta {
  display: flex;
  align-items: center;
  gap: 4px;
}

.dialog-footer {
  text-align: right;
}

:deep(.el-tree-node__content) {
  height: auto;
  padding: 8px 0;
}

:deep(.el-tree-node__label) {
  flex: 1;
}
</style>
